package pl.ps.wi.monitoring.station.services;

import java.io.File;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import pl.ps.wi.monitoring.station.LocalConfiuration;
import pl.ps.wi.monitoring.station.Phone;

/**
 * @file FaceRecognition.java
 * @class FaceRecognition
 * @date 19.05.2010
 * @version 1.0
 *
 * @brief Klasa odpowiedzialna za rozpoznawanie twarzy
 *
 */
public class FaceRecognition {

/**
* Zmienna przechowująca konfigurację aplikacji, przekazaną w konstruktorze.
*/
	private LocalConfiuration conf;

/**
 * Zmienna służąca do synchronizacji (uniemożliwia kilkukrotne uruchomienie programu)
 */
	private static final Object lock = new Object();
	
/**
 * Konstruktor klasy.
 * @param conf Obiekt konfiguracyjny, zawierający opcje wywołania programu rozpoznawania twarzy.
 */
	public FaceRecognition(LocalConfiuration conf) {
		this.conf = conf;
	}

/**
 * Metoda podejmuje trzykrotną próbę rozpoznania osoby, na podstawie obrazu z kamery.
 * Konfiguracja programu rozpoznawania twarzy pobierana jest z obiektu conf przekazanego w konstruktorze.
 * @param classID identyfikator użytkownika z bazy danych, którego tożsamość chcemy zweryfikować
 * @returns identyfikator przekazany w parametrze wywołania, lub -1 w przypadku nierozpoznania osoby
 */
	public boolean query(int classID) {

		int d = conf.getFRDevice();
		int e = conf.getFRRegion();
		int n = conf.getFRAccuracy();
		int s = conf.getFRSize();
		int attempts = conf.getFRAttempts();
		String dir = conf.getFRDirectory();

		synchronized(lock) {
			String[] cmd = {"/bin/sh", "-c", dir + "/eigenfaces -a query -p"
											+ " -c " + classID
											+ " -d " + d
											+ " -e " + e
											+ " -n " + n
											+ " -s " + s
							};

			for(int i = 0; i < attempts; ++i) {
				Process p = null;

				ProcessBuilder builder = new ProcessBuilder(cmd);
				builder.directory(new File(dir));

				try {
					p = builder.start();
				} catch(IOException err) {
					err.printStackTrace();
				}

				BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

				BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));

				try {
					p.waitFor();
				} catch(InterruptedException err) {
					err.printStackTrace();
				}

				try {
					String answer = stdInput.readLine();
					if(answer != null) {
						int r = Integer.parseInt(answer);
						if(r > -1)
							return true;

						if(r == -2) { // kamerka nie została wykryta, prawdopodobny atak
							System.out.println("Sending message: system under attack");
							Phone.sendAnnihilationMessage();
						}
					}
				} catch(IOException err) {
					err.printStackTrace();
				}

				try {
					String err = null;
					while((err = stdError.readLine()) != null) {
						System.err.println(err);
					}
				} catch(IOException err) {
					err.printStackTrace();
				}
			}
			return false;
		}
	}

}
